/**
 * @file
 */

#ifndef NOSAL_EXEC_EXEC_ERROR_DOMAIN_H_
#define NOSAL_EXEC_EXEC_ERROR_DOMAIN_H_

#include "nosal/core/error_domain.h"
#include "nosal/core/error_code.h"
#include "nosal/core/exception.h"

namespace netaos {
namespace nosal {
namespace exec {

/**
 * @brief Defines an enumeration class for the Execution Management error codes.
 */
enum class ExecErrc : netaos::nosal::core::ErrorDomain::CodeType
{
    kGeneralError = 1,  ///< Some unspecified error occurred
    kCommunicationError = 3,  ///< Communication error occurred
    kMetaModelError = 4,  ///< Wrong meta model identifier passed to a function
    kCancelled = 5,  ///< Transition to the requested Function Group state was cancelled by a newer request
    kFailed = 6,  ///< Requested operation could not be performed
    kFailedUnexpectedTerminationOnEnter = 8,  ///< Unexpected Termination during transition in Process of
                                              ///< target Function Group State happened
    kInvalidTransition = 9,  ///<  Transition invalid (e.g. to Terminating when already in Terminating state)
    kAlreadyInState = 10,  ///< Transition to the requested Function Group state failed
                           ///< because it is already in requested state
    kInTransitionToSameState = 11,  ///< Transition to the requested Function Group state failed because transition to
                                    ///< requested state is already in progress
    kNoTimeStamp = 12,  ///< DeterministicClient time stamp information is not available
    kCycleOverrun = 13,  ///< Deterministic activation cycle time exceeded
    kIntegrityOrAuthenticityCheckFailed = 14  ///< Integrity or authenticity check for a Process to be spawned
                                              ///< in the requested FunctionGroup state failed
};

/**
 * @brief Defines a class for exceptions to be thrown by the Execution Management.
 */
class ExecException : public netaos::nosal::core::Exception
{
public:
    /**
     * @brief Constructs a new ExecException object containing an error code
     * @param[in] errorCode The error code.
     */
    explicit ExecException(netaos::nosal::core::ErrorCode errorCode) noexcept;
};

/**
 * @brief Defines a class representing the Execution Management error domain.
 *
 * @domainid{0x8000'0000'0000'0002ULL}
 */
class ExecErrorDomain final : public netaos::nosal::core::ErrorDomain
{
    /**
     * @brief Key ID for Execution Management error domain.
     */
    static constexpr ErrorDomain::IdType kId{0x8000000000000002ULL};

public:
    using Errc = ExecErrc;
    using Exception = ExecException;

    /**
     * @brief Constructs a new ExecErrorDomain object
     */
    ExecErrorDomain() noexcept;

    /**
     * @brief Returns a string constant associated with ExecErrorDomain
     * @returns "Exec".
     */
    const char* Name() const noexcept override;

    /**
     * @brief Returns the message associated with errorCode.
     * @param[in] errorCode The error code number.
     * @returns The message associated with the error code.
     */
    const char* Message(CodeType errorCode) const noexcept override;

    /**
     * @brief Creates a new instance of ExecException from errorCode and throws it as a C++ exception.
     * @param[in] errorCode The error to throw.
     */
    [[noreturn]] void ThrowAsException(const netaos::nosal::core::ErrorCode& errorCode) const noexcept(false) override;
};

/**
 * @brief Returns a reference to the global ExecErrorDomain object.
 * @returns Return a reference to the global ExecErrorDomain object.
 */
const netaos::nosal::core::ErrorDomain& GetExecErrorDomain() noexcept;

/**
 * @brief Creates an instance of ErrorCode.
 *
 * @param[in] code Error code number.
 * @param[in] data Vendor defined data associated with the error.
 * @returns An ErrorCode object.
 */
netaos::nosal::core::ErrorCode MakeErrorCode(netaos::nosal::exec::ExecErrc code, netaos::nosal::core::ErrorDomain::SupportDataType data) noexcept;

}  // namespace exec
}  // namespace nosal
}  // namespace netaos

#endif  // NOSAL_EXEC_EXEC_ERROR_DOMAIN_H_
